Crate repr_offset
source ·Expand description
repr_offset
allows computing and safely using field offsets from types
with a defined layout.
Currently only #[repr(C)]
/#[repr(C,packed)]
/#[repr(C,align)]
structs are supported.
Features
These are some of the features this library provides:
-
The
ReprOffset
derive macro, which outputs associated constants with the offsets of fields, and implements theGetFieldOffset
trait for each field. -
The
FieldOffset
type (how offsets are represented), with methods for operating on a field through a pointer to the struct, including getting a reference(or pointer) to the field. -
The
unsafe_struct_field_offsets
macro as an alternative to theReprOffset
derive macro, most useful when the “derive” feature is disabled. -
The
GetFieldOffset
trait, for getting theFieldOffset
for a field, and theOFF!
,off
,PUB_OFF!
, andpub_off
macros for getting theFieldOffset
for a field with a convenient syntax. -
The extension traits from the
ext
module, which define methods for operating on a field, given aFieldOffset
.
Examples
Derivation
This example demonstrates:
-
Deriving the field offset constants and
GetFieldOffset
trait with theReprOffset
derive macro. -
Moving out unaligned fields through a raw pointer.
use repr_offset::ReprOffset;
use repr_offset::{ROExtRawOps, off};
use std::mem::ManuallyDrop;
#[repr(C, packed)]
#[derive(ReprOffset)]
struct Packed{
x: u8,
y: u64,
z: String,
}
let mut this = ManuallyDrop::new(Packed{
x: 5,
y: 8,
z: "oh,hi".to_string(),
});
let ptr: *mut Packed = &mut *this;
unsafe{
assert_eq!( Packed::OFFSET_X.read(ptr), 5 );
assert_eq!( Packed::OFFSET_Y.read(ptr), 8 );
assert_eq!( Packed::OFFSET_Z.read(ptr), "oh,hi".to_string() );
// Another way to do the same, using extension traits, and macros.
assert_eq!( ptr.f_read(off!(x)), 5 );
assert_eq!( ptr.f_read(off!(y)), 8 );
}
Initialization
This example demonstrates how you can:
-
Use the
unsafe_struct_field_offsets
macro to declare associated constants with the field offsets, and implement theGetFieldOffset
trait. -
Initialize an uninitialized struct with a functino that takes a raw pointer.
use std::mem::MaybeUninit;
use repr_offset::{
unsafe_struct_field_offsets,
off,
Aligned, ROExtRawMutOps,
};
fn main(){
unsafe {
let mut foo = MaybeUninit::<Foo>::uninit();
initialize_foo(foo.as_mut_ptr());
assert_eq!(
foo.assume_init(),
Foo{ name: "foo".to_string(), x: 13, y: 21 }
);
}
}
/// Initializes a `Foo` through a raw pointer.
///
/// # Safety
///
/// Callers must pass a pointer to uninitialized memory with the
/// size and alignment of `Foo`
unsafe fn initialize_foo(this: *mut Foo){
// How it's done with the inherent associated constants declared in
// the `unsafe_struct_field_offsets` macro
//
Foo::OFFSET_NAME.write(this, "foo".into());
Foo::OFFSET_X.write(this, 13);
Foo::OFFSET_Y.write(this, 21);
// How it's done with the extension traits from the ext module,
// the `off` macro, and the `GetFieldOffset` trait:
//
// this.f_write(off!(name), "foo".into());
// this.f_write(off!(x), 13);
// this.f_write(off!(y), 21);
}
#[repr(C)]
#[derive(Debug, PartialEq)]
pub struct Foo{
pub name: String,
pub x: u32,
pub y: u32,
}
// This macro is unsafe to invoke because you have to ensure that:
// - All field types are listed,in declaration order.
// - The `alignment` parameter is `Unaligned` if the struct is `#[repr(C,packed)]`,
// and `Aligned` if it's not.
unsafe_struct_field_offsets!{
alignment = Aligned,
impl[] Foo {
pub const OFFSET_NAME, name: String;
pub const OFFSET_X, x: u32;
pub const OFFSET_Y, y: u32;
}
}
Dependencies
This library re-exports the ReprOffset
derive macro from the
repr_offset_derive
crate when the “derive” feature is enabled,
this is disabled by default.
It also reexports the tstr
crate unconditionally, to use its TS
macro
as the type parameter of the GetFieldOffset
trait.
Cargo features
These are the cargo features in repr_offset
:
-
derive
(disabled by default): Enables theReprOffset
derive macro. This requires the same Rust versions assyn
, which is currently>= 1.56.0
. -
"for_examples"
(disabled by default): Enables thefor_examples
module, with types used in documentation examples.
Example of using the “derive” feature::
repr_offset = { version = "0.2", features = ["derive"] }
no-std support
This library is unconditionally #![no_std]
, and that is unlikely to change in the future.
Minimum Rust version
This crate support Rust back to 1.41.0.
Re-exports
pub use tstr;
pub use self::alignment::Aligned;
pub use self::alignment::Unaligned;
pub use self::ext::ROExtAcc;
pub use self::ext::ROExtOps;
pub use self::ext::ROExtRawAcc;
pub use self::ext::ROExtRawMutAcc;
pub use self::ext::ROExtRawMutOps;
pub use self::ext::ROExtRawOps;
pub use self::get_field_offset::FieldType;
pub use self::get_field_offset::GetPubFieldOffset;
Modules
- Type-level encoding of
enum Alignment { Aligned, Unaligned }
- Extension traits that use
FieldOffset
parameters to operate on fields. - for_examples
for_examples
Types used for examples, - Trait for getting the
FieldOffset
of a field, and related items. - Functions for calculating field offsets.
- Type-level encoding of
enum Privacy { IsPublic, IsPrivate }
- Miscelaneous functions.
Macros
- Gets the
FieldOffset
for the passed in type and (possibly nested) field. - Gets the
FieldOffset
for the passed in type and (possibly nested) public field. - Gets the
FieldOffset
for a (possibly nested) field, and an optionally passed in value. - Gets the
FieldOffset
for a (possibly nested) public field, and an optionally passed in value. - Declares a sequence of associated constants with the offsets of the listed fields, and implements the
GetFieldOffset
trait.
Structs
- Represents the offset of a (potentially nested) field inside a type.
Derive Macros
- ReprOffset
derive
TheReprOffset
derive macro defines associated constants with the offset of every field, and implements theGetFieldOffset
trait,